#include "Game.hpp"
#include "..\Entity\Entity.hpp"

#include <iostream>


Game* Game::m_inst = NULL;

Game::Game()
{
	//-
}

Game::~Game()
{
	//-
}

int Game::launch()
{
	try
	{
		m_debug = false;
		m_running = true;
		m_step = (float)(1./60.);
		m_window.create(sf::VideoMode(800,600), "jcnf");
		m_window.setFramerateLimit(60);
		m_view.reset(sf::FloatRect(0, 0, 800, 600));
		//\todo m_map.loadMap(mapName);
		m_transition = -1;
		m_shade.setPosition(0.,0.);
		m_shade.setFillColor(sf::Color(0,0,0,0));
		m_shade.setSize(sf::Vector2f(800.,600.));
		m_map.loadMap1();
		if(m_window.isOpen())
			mainLoop();
		else
			return EXIT_FAILURE;
	}
	catch(string str)
	{
		std::cerr << "String Exception : " << str << std::endl;
		return EXIT_FAILURE;
	}
	catch(...)
	{
		std::cerr << "Exception" << std::endl;
		return EXIT_FAILURE;
	}

	return EXIT_SUCCESS;
}

const Input& Game::getInput() const
{
	return m_input;
}

Map& Game::getMap()
{
	return m_map;
}

void Game::mainLoop()
{
	m_player = new Player();
	m_player->setPosition(150, 50);
	while(m_running)
	{
		sortEvents();
		update();
		updateHUD();
		draw();
	}
	Entity::clearAll();
	m_window.close();
}


///////////////Main loop functions ////////////////

void Game::sortEvents()
{
	sf::Event event;
	while(m_window.pollEvent(event))
	{
		if (event.type == sf::Event::Closed)
			m_running = false;
		else
		{
			m_input.pushEvent(event);
			m_debug = m_input.isKeyDown(Input::Debug_Key);
		}
	}
}

#define MAX_TRANSITION 10

void Game::update()
{
	if(m_transition >= MAX_TRANSITION)
	{
		//m_map.loadMap(mapName);
		switch(m_nextMap)
		{
		case 1:
			m_map.loadMap1();
			break;
		case 2:
			m_map.loadMap2();
			break;
		case 3:
			m_map.loadMap3();
			break;
		default:
			break;
		}
		//move Character
		m_player->setPosition(m_destination.x, m_destination.y);
		m_transition = -MAX_TRANSITION;
	}
	else if(m_transition >= 0)
	{
		m_transition++;
		m_shade.setFillColor(sf::Color(0,0,0,256*m_transition/MAX_TRANSITION));
	}
	else if(m_transition < -1)
	{
		m_transition++;
		m_shade.setFillColor(sf::Color(0,0,0,256 - 256*m_transition/MAX_TRANSITION));
	}
	else
	{
		Entity::UpdateAll();
		//detect map transition & change map if needed
		unsigned int nextMap;
		sf::Vector2f destination;
		if(m_map.changeMap(m_player,nextMap,destination))
		{
			switch(nextMap)
			{
			case 1:
			case 2:
			case 3:
				m_destination = destination;
				m_nextMap = nextMap;
				m_transition = 0;
				break;
				break;
			default: //could be an error
				break;
			}
		}

	}
	setView();
}

void Game::setView()
{
	float x = m_player->centralX();
	if(x - m_window.getSize().x/2.f < 0)
	{
		x = m_window.getSize().x/2.f;
		if(x + m_window.getSize().x/2. > m_map.width()) //center the view;
		{
			x = m_map.width() / 2.f;
		}
	}
	else if (x + m_window.getSize().x/2.f > m_map.width())
	{
		x = m_map.width() - m_window.getSize().x/2.f;
		if(x - m_window.getSize().x/2.f < 0) //center the view;
		{
			x = m_map.width() / 2.f;
		}
	}

	
	float y = m_player->centralY();
	if(y - m_window.getSize().y/2.f < 0)
	{
		y = m_window.getSize().y/2.f;
		if(y + m_window.getSize().y/2.f > m_map.height()) //center the view;
		{
			y = m_map.height() / 2.f;
		}
	}
	else if (y + m_window.getSize().y/2.f > m_map.height())
	{
		y = m_map.height() - m_window.getSize().y/2.f;
		if(y - m_window.getSize().y/2.f < 0) //center the view;
		{
			y = m_map.height() / 2.f;
		}
	}

	m_view.setCenter(x,y);
	m_shade.setPosition(x-400.f,y-300.f);
	//m_view.setCenter(x,m_window.getSize().y);
}

void Game::updateHUD()
{
	//\todo
}

void Game::draw()
{
	m_window.clear();
	m_window.setView(m_view);
	m_map.draw(m_window);
	Drawable::DrawAll();
	//\todo draw HUD
	if(m_transition != -1)
		m_window.draw(m_shade);
	m_window.display();
}
